import string, random, os
from PIL import Image, ImageFont, ImageDraw, ImageFilter

from django_redis import get_redis_connection  # 连接池
from config.dbs.redis_rev import LOGIN_KEY_TEMPLATE, EXPIRE_TIME  # 键，过期时间


# 验证码类
class ImageVerify:
    def __init__(self, x=140, y=40, length=4, size=28):
        """
        初始化
        :param x: 图片宽度
        :param y: 图片高度
        :param length: 字符个数
        :param size: 字体大小
        """
        self.x = x
        self.y = y
        self.length = length
        self.size = size

    def random_str(self):
        """
        验证码
        随机生成4个验证码字符
        26个字母和数字
        :return: 字符串验证码
        """
        source = string.ascii_letters + string.digits
        return ''.join(random.sample(source, self.length))

    def random_color(self, start=0, end=255):  # RGB 0-255
        """
        随机生成RGB颜色
        :param start: 颜色最小值
        :param end:   最大值
        :return: tuple(r,g,b) (0-255,0-255,0-255)
        """
        res = [random.randint(start, end) for i in range(3)]
        return tuple(res)

    def random_lines(self, draw):  # 画笔
        """
        绘制干扰线
        :param draw: 对象，画笔
        :return:
        """

        for i in range(self.length):  # 线条 4
            lines = [(random.randint(0, self.x), random.randint(0, self.y)) for i in range(2)]  # 一条线
            # 划线
            draw.line(lines, fill=self.random_color(64, 200))

    def random_points(self, draw, rate):
        """
        画点
        :param draw: 画笔
        :param rate: 频率，决定点的个数 50
        :return:
        """
        # 获取每个点位
        for x in range(self.x):
            for y in range(self.y):
                # 随机决定生成多少个点
                if random.randint(1, 100) <= rate:
                    draw.point((x, y), fill=self.random_color(64, 200))

    def verify_code(self):
        """
        生成验证码图片
        :return: 返回图片及验证码字符
        """

        # 创建画布 图
        image = Image.new('RGB', (self.x, self.y), (255, 255, 255))
        # 创建字体font
        file = os.path.dirname(os.path.abspath(__file__))  # 当前文件绝对路径
        font = ImageFont.truetype(fr'{file}/HYYakuHei-85W.ttf', self.size)

        draw = ImageDraw.Draw(image)  # 在该图创建画笔

        # 干扰线和干扰点
        self.random_lines(draw)
        self.random_points(draw, 15)
        # 验证码
        code = self.random_str()

        for i in range(self.length):
            draw.text((35 * i + 5, 3), code[i], font=font, fill=self.random_color(64, 200))

        image = image.filter(ImageFilter.BLUR)  # 模糊处理

        return image, code  # 图片验证码，验证码的值


# 自定义token方法
def jwt_token(token, user=None, request=None):
    """
    自定登陆后响应的函数，返回指定登录接口的数据，包括token
    :param token: 令牌
    :param user: 登录的用户对象
    :param request: 请求对象
    :return: token
    """

    param = request.data  # 参数
    uuid = param.get('uuid')
    verify = param.get('verify')

    if not uuid or not verify:
        return {'msg': '请输入验证码'}

    cache = get_redis_connection(alias='verify_codes')  # 1号库
    redis_verify = cache.get(LOGIN_KEY_TEMPLATE % uuid)  # 获取数据库验证码值
    cache.delete(LOGIN_KEY_TEMPLATE % uuid)  # 删除已经使用过的验证码

    if not redis_verify:  # 有没有验证码
        return {'msg': '验证码过期'}

    if redis_verify.upper() != verify.upper():  # 对比输入的验证码是否和数据库一致
        return {'msg': '验证码错误！'}

    return {
        'token': token,  # token
        'id': user.id,  # id
        'username': user.username,  # 用户
        'avatar': user.userdetail.avatar if hasattr(user, 'userdetail') else None  # 头像
    }


if __name__ == '__main__':
    imgVerify = ImageVerify()  # 实例化类
    img, code = imgVerify.verify_code()  # 拆包

    # with open('yzm.png', 'wb') as fp:
    #     img.save(fp)
    print(code)
